﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Transactions;
using System.Web;

namespace EComAssignment.Models
{
    public class AccountModel
    {
        public static bool isUserExist(string username)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var acc = (from a in ctx.Accounts
                       where a.username.Equals(username)
                       select a.ID);
            if (acc.Count() > 0)
            {
                return true;
            }
            return false;
        }
        public static bool sendConfirmResetPassword(string username, int port)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var acc = (from a in ctx.Accounts
                       where a.username == username
                       select new { a.email, a.ID }).SingleOrDefault();
            if (acc != null)
            {
                string title = "Thư reset mật khẩu từ Phan Anh SHOP";
                string body = "Có một yêu cầu reset mật khẩu từ tài khoản quý khách\n"
                    +"Quý khách click vào link sau để reset mật khẩu "
                    + "http://phananhshop.somee.com/Account/resetPassword?username=" + username + "&id=" + acc.ID
                    +"\nNếu không phải yêu cầu từ quý khách thì xin quý khách bỏ qua email này";
                sendEmail(acc.email, title, body);
                return true;
            }
            return false;
        }
        public static void resetPassword(string username, string id, int port)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            int accID = 0;
            try
            {
                accID = Int32.Parse(id);
            }
            catch (Exception) { }
            var acc = (from a in ctx.Accounts
                       where a.username == username && a.ID == accID
                       select a).SingleOrDefault();
            if (acc != null)
            {
                string newPass = createRandomString(8);
                acc.password = newPass;
                ctx.SubmitChanges();
                string title = "Thư reset mật khẩu từ Phan Anh SHOP";
                string body = "Mật khẩu mới là: " + newPass;
                sendEmail(acc.email, title, body);
            }
        }
        public static void sendActiveMail(string toEmail, int port, int id, string username)
        {
            
            string title = "Thư kích hoạt từ Phan Anh SHOP";
            string body = "Xin quý khách click vào link bên dưới để kích hoạt tài khoản \n"
                + "http://phananhshop.somee.com/Account/ActiveAccount?id=" + id + "&username=" + username;
            sendEmail(toEmail, title, body);
        }
        public static void sendEmail(string toEmail, string title, string body)
        {
            string from = "hackethicdemo@gmail.com";
            string pass = "nguyenthihong";
            var client = new SmtpClient("smtp.gmail.com", 587)
            {
                Credentials = new NetworkCredential(from, pass),
                EnableSsl = true
            };
            client.Send(from, toEmail, title, body);          
        }
        public static void sendActiveCode(string username, int port)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var acc = (from a in ctx.Accounts
                       where a.username == username
                       select new { a.ID, a.email }).SingleOrDefault();
            if (acc != null)
            {
                sendActiveMail(acc.email, port, acc.ID, username);
            }
        }
        public static bool createAccount(string username, string password, string fullName, string email, string address, string phoneNumber, int port)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            Account newAcc = new Account();
            newAcc.username = username;
            newAcc.password = password;
            newAcc.full_name = fullName;
            newAcc.email = email;
            newAcc.address = address;
            newAcc.phone_number = phoneNumber;
            newAcc.user_level = 3;
            ctx.Accounts.InsertOnSubmit(newAcc);
            try
            {
                ctx.SubmitChanges();
                sendActiveMail(email,port,newAcc.ID,username);
            }
            catch (Exception e)
            {
                string error = e.Message;
                return false;
            }
            return true;
        }
        public static bool activeAccount(string id, string username)
        {
            int accID = 0;
            try
            {
                accID = Int32.Parse(id);
            }
            catch (Exception) { }
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var acc = (from a in ctx.Accounts
                       where a.ID == accID && a.username == username
                       select a).FirstOrDefault();
            if (acc != null)
            {
                acc.user_level = 2;
                ctx.SubmitChanges();
                return true;
            }
            return false;
        }
        public static Account checkLogin(string username, string password)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var result = (from acc in ctx.Accounts
                          where acc.username.Equals(username) && acc.password.Equals(password)
                          select acc).FirstOrDefault();
            if (result != null)
            {
                return result;
            }
                        
            return null;
        }

        private static string createRandomString(int length)
        {
            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            var random = new Random();
            var result = new string(
                Enumerable.Repeat(chars, length)
                          .Select(s => s[random.Next(s.Length)])
                          .ToArray());
            return result;
        }

        public static bool changePassword(string username, string oldPass, string newPass)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var acc = (from a in ctx.Accounts
                       where a.username == username && a.password == oldPass
                       select a).SingleOrDefault();
            if (acc != null)
            {
                acc.password = newPass;
                ctx.SubmitChanges();
                return true;
            }
            return false;
        }

        public static bool checkout(string username, Dictionary<int, int> cart)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var acc = (from a in ctx.Accounts
                       where a.username == username
                       select a).SingleOrDefault();
            if (acc == null)
            {
                return false;
            }

            Order order = new Order() 
            { 
            customer_ID = acc.ID,
            order_date = DateTime.Now,
            status = "waiting",
            subtotal = 0,
            tax = 0,
            total = 0
            };
            using (System.Transactions.TransactionScope tScope
                = new System.Transactions.TransactionScope(TransactionScopeOption.Required))
            {
                try
                {                    
                    ctx.Orders.InsertOnSubmit(order);
                    ctx.SubmitChanges();
                    foreach (var detail in cart)
                    {
                        var pro = ctx.Products.Where(p => p.ID == detail.Key).FirstOrDefault();
                        if (pro == null)
                        {                         
                            return false;
                        }
                        if (pro.capacity < detail.Value)
                        {
                            return false;
                        }
                        var proPrice = pro.price;
                        if (pro.promotion_ID.HasValue)
                        {
                            if (pro.Promotion.start_date <= DateTime.Now && DateTime.Now <= pro.Promotion.end_date)
                            {
                                proPrice = pro.price / 100 * (100 - pro.Promotion.rate);
                            }
                        }
                        Order_Detail orderDetail = new Order_Detail()
                        {
                            order_ID = order.ID,
                            product_ID = detail.Key,
                            quantity = detail.Value,
                            price = proPrice,
                            total = proPrice * detail.Value
                        };
                        ctx.Order_Details.InsertOnSubmit(orderDetail);                        
                        order.subtotal += orderDetail.total;
                        pro.capacity -= detail.Value;
                        ctx.SubmitChanges();
                    }
                    order.tax = order.subtotal / 10;
                    order.total = order.subtotal + order.tax;

                    ctx.SubmitChanges();
                    tScope.Complete();
                }
                catch (Exception e)
                {                    
                    return false;
                }
            }
            return true;
        }

        public static bool removeOrder(int orderID)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var orderDetailList = (from od in ctx.Order_Details
                                   where od.order_ID == orderID
                                   select od);
            try
            {
                foreach (var od in orderDetailList)
                {
                    var pro = ctx.Products.Where(p => p.ID == od.product_ID).SingleOrDefault();
                    pro.capacity += od.quantity;
                    ctx.SubmitChanges();
                }
                ctx.Order_Details.DeleteAllOnSubmit(orderDetailList);
                var order = (from o in ctx.Orders
                             where o.ID == orderID
                             select o).SingleOrDefault();                
                ctx.Orders.DeleteOnSubmit(order);
                ctx.SubmitChanges();
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        public static bool updateQuantityOrderDetail(Dictionary<int, int> tmpOrder,int orderID)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            try
            {                
                foreach (var or in tmpOrder)
                {
                    var ode = (from od in ctx.Order_Details
                               where od.ID == or.Key
                               select od).SingleOrDefault();
                    if (ode != null)
                    {
                        var pro = ctx.Products.Where(p => p.ID == ode.product_ID).SingleOrDefault();
                        pro.capacity += ode.quantity;
                        if (or.Value > 0)
                        {                            
                            ode.quantity = or.Value;
                            pro.capacity -= ode.quantity;
                        }
                        else if(or.Value == 0)  //remove order detail has 0 quantity
                        {
                            ctx.Order_Details.DeleteOnSubmit(ode);
                        }
                        ctx.SubmitChanges();
                    }
                }

                return updateOrder(orderID);          
            }
            catch (Exception e)
            {
                return false;
            }            
        }

        public static bool removeOrderDetail(int orderDetailID)
        {
            DataClasses1DataContext ctx= new DataClasses1DataContext();
            var orderDetail = (from od in ctx.Order_Details
                               where od.ID == orderDetailID
                               select od).SingleOrDefault();
            if (orderDetail == null) { return false; }
            int orderID = orderDetail.order_ID;
            try
            {
                var pro = ctx.Products.Where(p => p.ID == orderDetail.product_ID).SingleOrDefault();
                pro.capacity += orderDetail.quantity;
                ctx.Order_Details.DeleteOnSubmit(orderDetail);
                ctx.SubmitChanges();
                return updateOrder(orderID);                
            }
            catch (Exception e)
            {
                return false;
            }            
        }

        //delete order has not order detail and computing again total in orderdetail and order
        private static bool updateOrder(int orderID)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            try
            {
                var order = (from o in ctx.Orders
                             where o.ID == orderID
                             select o).SingleOrDefault();
                if (order == null) { return false; }
                var orderDetail = (from od in ctx.Order_Details
                                   where od.order_ID == orderID
                                   select od);
                if (orderDetail.Count() == 0)
                {
                    ctx.Orders.DeleteOnSubmit(order);
                    ctx.SubmitChanges();
                    return false;
                }
                decimal subTotal = 0;
                foreach (var od in orderDetail)
                {
                    od.total = od.quantity * od.price;
                    subTotal += od.total;
                }
                order.subtotal = subTotal;
                order.tax = subTotal / 10;
                order.total = subTotal + order.tax;
                ctx.SubmitChanges();
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        public static bool addCartToOrder(int orderID, Dictionary<int,int> cart)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();            
            try
            {
                foreach (var detail in cart)
                {
                    var ode = ctx.Order_Details.Where(od => od.order_ID == orderID
                        && od.product_ID == detail.Key).FirstOrDefault();
                    if (ode != null)
                    {
                        ode.quantity += detail.Value;                        
                    }
                    else
                    {
                        var pro = ctx.Products.Where(p => p.ID == detail.Key).FirstOrDefault();
                        if (pro == null) { return false; }

                        var proPrice = pro.price;
                        if (pro.promotion_ID.HasValue)
                        {
                            if (pro.Promotion.start_date <= DateTime.Now 
                                && DateTime.Now <= pro.Promotion.end_date)
                            {
                                proPrice = pro.price / 100 * (100 - pro.Promotion.rate);
                            }
                        }
                        Order_Detail orderDetail = new Order_Detail()
                        {
                            order_ID = orderID,
                            product_ID = detail.Key,
                            quantity = detail.Value,
                            price = proPrice,
                            total = proPrice * detail.Value
                        };
                        ctx.Order_Details.InsertOnSubmit(orderDetail);                        
                    }
                    ctx.SubmitChanges();
                }
                return updateOrder(orderID);
            }
            catch (Exception e)
            {
                return false;
            }            
        }

        public static bool saveWishlist(int proID, string username)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var user = ctx.Accounts.Where(a => a.username == username).SingleOrDefault();
            if (user == null) { return false; }
            var wis = ctx.Wishlists.Where(w => w.product_ID == proID && w.customer_ID == user.ID).SingleOrDefault();
            if (wis != null) { return false; }
            Wishlist wish = new Wishlist() 
            { 
                customer_ID = user.ID,
                product_ID = proID,
                wish_date = DateTime.Now,
                status = "wishing"
            };
            try
            {
                ctx.Wishlists.InsertOnSubmit(wish);
                ctx.SubmitChanges();
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        public static bool deleteAllWishlist(string username)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var user = ctx.Accounts.Where(a => a.username == username).SingleOrDefault();
            if (user == null) { return false; }
            var wishlist = ctx.Wishlists.Where(w => w.customer_ID == user.ID);
            try
            {
                ctx.Wishlists.DeleteAllOnSubmit(wishlist);
                ctx.SubmitChanges();
            }
            catch (Exception e)
            {
                return false;
            }
            return true;
        }

        public static bool deleteWishlist(string username, int proID)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var user = ctx.Accounts.Where(a => a.username == username).SingleOrDefault();
            if (user == null) { return false; }
            var wish = ctx.Wishlists.Where(w => w.customer_ID == user.ID && w.product_ID == proID).SingleOrDefault();
            if (wish == null) { return false; };
            try
            {
                ctx.Wishlists.DeleteOnSubmit(wish);
                ctx.SubmitChanges();
            }catch(Exception e)
            {
                return false;
            }
            return true;
        }

        public static int getCapacity(int proID)
        {
            DataClasses1DataContext ctx = new DataClasses1DataContext();
            var pro = ctx.Products.Where(p => p.ID == proID).SingleOrDefault();
            if (pro == null) { return 0; }
            return pro.capacity;
        }
    }
}